package sql.parser;

import org.apache.commons.lang3.StringUtils;
import sql.lexer.SQLLexer;

public class UpdateParser extends SelectParser {
    public UpdateParser(SQLLexer lexer) {
        super(lexer);
    }

    public SyntaxNode updateParse() {
        this.nextToken();
        SyntaxNode sqlNode = new SyntaxNode(SyntaxNodeType.Sql);
        if(updateSql(sqlNode) && this.isEnd()) {
            return sqlNode;
        } else {
            return null;
        }
    }

    private boolean updateSql(SyntaxNode sqlNode) {
        if(this.getSyntaxType() == SyntaxType.Update) {
            nextToken();
            if(this.getSyntaxType() == SyntaxType.Identifier) {
                SyntaxNode fromNode = new SyntaxNode(SyntaxNodeType.From, this.getStrToken());
                sqlNode.setFromNode(fromNode);
                nextToken();
                if(this.getSyntaxType() == SyntaxType.Set) {
                    nextToken();
                    if(!updatePairs(sqlNode)) {
                        return false;
                    } else {
                        if(this.isEnd()) {
                            return true;
                        } else {
                            if(this.getSyntaxType() == SyntaxType.Where) {
                                nextToken();
                                if(!conditions(sqlNode)) {
                                    return false;
                                }  else {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    private boolean updatePair(SyntaxNode updateNode) {
        SyntaxNode pair = new SyntaxNode(SyntaxNodeType.UpdatePair);
        updateNode.addChild(pair);
        if(getSyntaxType() == SyntaxType.Identifier) {
            pair.addChild(new SyntaxNode(SyntaxNodeType.UpdatePairItem,this.getStrToken()));
            nextToken();
            if(StringUtils.equals(getStrToken(),"=")) {
                pair.addChild(new SyntaxNode(SyntaxNodeType.UpdatePairItem,"="));
                nextToken();
                if(getSyntaxType() == SyntaxType.BracketStart) {
                    nextToken();
                    SyntaxNode sqlNode = new SyntaxNode(SyntaxNodeType.UpdatePairItem);
                    pair.addChild(sqlNode);
                    if(!sql(sqlNode)) {
                        return false;
                    } else {
                        if(getSyntaxType() == SyntaxType.BracketEnd) {
                            nextToken();
                            return true;
                        } else {
                            return false;
                        }
                    }
                } else if(isElement(getSyntaxType())) {
                    pair.addChild(new SyntaxNode(SyntaxNodeType.UpdatePairItem,this.getStrToken()));
                    nextToken();
                    return true;
                }
            }
        }
        return false;
    }

    private boolean updatePairs(SyntaxNode sqlNode) {
        SyntaxNode updateNode = new SyntaxNode(SyntaxNodeType.Update);
        sqlNode.setUpdateNode(updateNode);
        if(!updatePair(updateNode)) {
            return false;
        } else {
            return updatePairsTail(updateNode);
        }
    }

    private boolean updatePairsTail(SyntaxNode updateNode) {
        if(this.getSyntaxType() == SyntaxType.Comma) {
            nextToken();
            if(!updatePair(updateNode)) {
                return false;
            } else {
                return updatePairsTail(updateNode);
            }
        } else if(this.getSyntaxType() == SyntaxType.Where) {
            return true;
        } else if(isEnd()) {
            return true;
        } else {
            return false;
        }
    }
}
